home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / comm / tcp / Amster.lha / Amster_Install / Source / navigator.c < prev    next >
C/C++ Source or Header  |  2000-07-31  |  14KB  |  462 lines

  1. /*
  2. ** Amster - Navigator
  3. ** by Jacob Laursen <laursen@myself.com>
  4. **
  5. ** (work in progress!)
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include <proto/dos.h>
  13. #include <proto/socket.h>
  14. #include <proto/utility.h>
  15.  
  16. #include <netdb.h>
  17. #include <sys/time.h>
  18. #include <sys/socket.h>
  19. #include <sys/ioctl.h>
  20. #include <netinet/tcp.h>
  21. #include <bsdsocket/socketbasetags.h>
  22. #include <error.h>
  23. #include <time.h>
  24.  
  25. #include <MUI/NListview_mcc.h>
  26.  
  27. #include "include/config.h"
  28. #include "include/gui.h"
  29. #include "include/info.h"
  30. #include "include/mui.h"
  31. #include "include/navigator.h"
  32. #include "include/prefs.h"
  33. #include "include/share.h"
  34.  
  35. #include "include/protos.h"
  36. #include "amster_Cat.h"
  37.  
  38. #define NAPIGATOR_REQ "GET /servers.php?version=108 HTTP/1.0\r\n\r\n"
  39.  
  40. /* Global variables */
  41.  
  42. BOOL ServerListChanged = FALSE;
  43.  
  44. /* Private prototypes */
  45.  
  46. void LoadServerList(struct NavigatorData *data);
  47. void SaveServerList(struct NavigatorData *data);
  48. void MarkServerOnline(struct NavigatorData *data, char *server);
  49. MUIF ServerListDisplay(REG(a2) char **array, REG(a1) struct ServerEntry *entry);
  50. MUIF ServerListCompare(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm);
  51. MUIF ServerListDestruct(REG(a2) APTR pool, REG(a1) struct ServerEntry *entry);
  52. MUIF ServerString(REG(a0) struct Hook *hook, REG(a1) APTR *contents);
  53. BOOL GetNapigatorList(struct NavigatorData *data);
  54. BOOL get_response(long sockfd, char *buf, int max);
  55. void UpdateFromNapigator(struct NavigatorData *data, char *list);
  56.  
  57.  
  58. MUIF NavigatorDispatch(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg)
  59. {
  60.     struct NavigatorData *data;
  61.     struct ServerEntry *entry;
  62.     char *buf;
  63.  
  64.     switch (msg->MethodID) {
  65.         case OM_NEW:
  66.             return(NavigatorNew(cl, obj, (APTR)msg));
  67.         case NAVI_CONNECT:
  68.             data = INST_DATA(cl, obj);
  69.             if (gui_onlinestate > OFFLINE) nap_logout();
  70.             get(data->ST_Server, MUIA_String_Contents, &buf);
  71.             if (gui_onlinestate < CONNECTING) {
  72.                 nap_login_fromlist(buf);
  73.             }
  74.             return NULL;
  75.         case NAVI_GETSERVER:
  76.             data = INST_DATA(cl, obj);
  77.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  78.             if (entry) {
  79.                 set(data->ST_Server,  MUIA_String_Contents, entry->Name);
  80.                 set(data->ST_Comment, MUIA_String_Contents, entry->Comment);
  81.             }
  82.             return NULL;
  83.         case NAVI_ADDSERVER:
  84.             {
  85.             BOOL selected = FALSE;
  86.  
  87.             data = INST_DATA(cl, obj);
  88.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  89.             if (entry) selected = TRUE;    /* One entry is already selected */
  90.  
  91.             if (entry = malloc(sizeof(struct ServerEntry))) {
  92.                 entry->LastOnline = 0;
  93.                 if (selected) {
  94.                     /* We clear the fields instead of dublicating selected entry */
  95.                     entry->Name = strdup(MSG_NAVIGATOR_NEW);
  96.                     entry->Comment = strdup("");
  97.                 }
  98.                 else {
  99.                     get(data->ST_Server, MUIA_String_Contents, &buf);
  100.                     entry->Name = strdup(buf);
  101.                     get(data->ST_Comment, MUIA_String_Contents, &buf);
  102.                     entry->Comment = strdup(buf);
  103.                 }
  104.                 DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  105.                 set(data->LV_Server, MUIA_NList_First, MUIV_NList_Active_Bottom);
  106. /*                DoMethod(data->LV_Server, MUIM_NList_Jump, MUIV_NList_Jump_Active);*/
  107.                 ServerListChanged = TRUE;
  108.             }
  109.             }
  110.             return NULL;
  111.         case NAVI_REMOVESERVER:
  112.             data = INST_DATA(cl, obj);
  113.             DoMethod(data->LV_Server, MUIM_NList_Remove, MUIV_NList_Remove_Active);
  114.             ServerListChanged = TRUE;
  115.             return NULL;
  116.         case NAVI_REDRAWSERVER:
  117.             {
  118.             struct ServerEntry *entry;
  119.             APTR *contents = (APTR)(((muimsg)msg)->arg1);
  120.             data = INST_DATA(cl, obj);
  121.  
  122.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  123.             if (entry) {
  124.                 if (*(contents+1) == 0) entry->Name = strdup(*contents);
  125.                 else entry->Comment = strdup(*contents);
  126.                 DoMethod(data->LV_Server, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  127.                 ServerListChanged = TRUE;
  128.             }
  129.             return NULL;
  130.             }
  131.         case NAVI_LOAD:
  132.             data = INST_DATA(cl, obj);
  133.             LoadServerList(data);
  134.             return NULL;
  135.         case NAVI_SAVE:
  136.             data = INST_DATA(cl, obj);
  137.             SaveServerList(data);
  138.             return NULL;
  139.         case NAVI_MARKSERVER:
  140.             data = INST_DATA(cl, obj);
  141.             MarkServerOnline(data, (char *)(((muimsg)msg)->arg1));
  142.             return NULL;
  143.     }
  144.     return(DoSuperMethodA(cl, obj, msg));
  145. }
  146.  
  147.  
  148. ULONG NavigatorNew(struct IClass *cl, Object *obj, struct opSet *msg)
  149. {
  150.     static const struct Hook ServerListDispHook = { {NULL, NULL}, &ServerListDisplay,  NULL, NULL };
  151.     static const struct Hook ServerListCompHook = { {NULL, NULL}, &ServerListCompare,  NULL, NULL };
  152.     static const struct Hook ServerListDestHook = { {NULL, NULL}, &ServerListDestruct, NULL, NULL };
  153.     static const struct Hook ServerStringHook   = { {NULL, NULL}, &ServerString,       NULL, NULL };
  154.  
  155.     struct NavigatorData *data;
  156.  
  157.     Object *LV_Server, *ST_Server, *ST_Comment;
  158.     Object *BT_ConnectConnect, *BT_ConnectAdd, *BT_ConnectRemove;
  159.  
  160.     if (obj = (Object *)DoSuperNew(cl, obj,
  161.         MUIA_HelpNode, "navi",
  162.         MUIA_Window_Title, MSG_NAVIGATOR_TITLE,
  163.         MUIA_Window_ID, MAKE_ID('N','A','V','I'),
  164.         WindowContents, VGroup,
  165.             Child, LV_Server = NListviewObject,
  166.                 MUIA_NList_Input, TRUE,
  167.                 MUIA_NListview_NList, NListObject,
  168.                     InputListFrame,
  169.                     MUIA_NList_ListBackground, MUII_ListBack,
  170.                     MUIA_NList_TitleBackground, MUII_ListBack,
  171.                     MUIA_NList_Title, TRUE,
  172.                     MUIA_NList_Format, "BAR,BAR,",
  173.                     MUIA_NList_DisplayHook, &ServerListDispHook,
  174.                     MUIA_NList_CompareHook2, &ServerListCompHook,
  175.                     MUIA_NList_DestructHook, &ServerListDestHook,
  176.                 End,
  177.             End,
  178.             Child, ColGroup(2),
  179.                 Child, Label2(MSG_NAVIGATOR_SERVER),
  180.                 Child, ST_Server = StringObject,
  181.                     MUIA_HorizWeight, 400,
  182.                     StringFrame,
  183.                 End,
  184.                 Child, Label2(MSG_NAVIGATOR_COMMENT),
  185.                 Child, ST_Comment = StringObject,
  186.                     MUIA_HorizWeight, 400,
  187.                     StringFrame,
  188.                 End,
  189.             End,
  190.             Child, RectangleObject,
  191.                 MUIA_FixHeight, 8,
  192.                 MUIA_Rectangle_HBar, TRUE,
  193.             End,
  194.             Child, HGroup,
  195.                 Child, BT_ConnectConnect = SimpleButton(MSG_NAVIGATOR_CONNECT_GAD),
  196.                 Child, BT_ConnectRemove  = SimpleButton(MSG_NAVIGATOR_REMOVE_GAD),
  197.                 Child, BT_ConnectAdd     = SimpleButton(MSG_NAVIGATOR_ADD_GAD),
  198.             End,
  199.         End,
  200.         TAG_MORE, msg->ops_AttrList))
  201.     {
  202.         data = INST_DATA(cl, obj);
  203.         data->LV_Server  = LV_Server;
  204.         data->ST_Server  = ST_Server;
  205.         data->ST_Comment = ST_Comment;
  206.  
  207.         DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, obj, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  208.  
  209.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick,  MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  210.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
  211.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType,    MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark,  MUIV_TriggerValue);
  212.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType2,   MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
  213.  
  214.         DoMethod(BT_ConnectConnect, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_CONNECT);
  215.         DoMethod(BT_ConnectRemove,  MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_REMOVESERVER);
  216.         DoMethod(BT_ConnectAdd,     MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_ADDSERVER);
  217.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, NAVI_CONNECT);
  218.  
  219.         LoadServerList(data);
  220.  
  221.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_Active, MUIV_EveryTime, obj, 1, NAVI_GETSERVER);
  222.  
  223.         set(ST_Server, MUIA_String_AttachedList, LV_Server);
  224.  
  225.         DoMethod(ST_Server,  MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 0);
  226.         DoMethod(ST_Comment, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 1);
  227.  
  228.         return((ULONG)obj);
  229.     }
  230.     return(0);
  231. }
  232.  
  233.  
  234. void LoadServerList(struct NavigatorData *data)
  235. {
  236.     BPTR fh;
  237.     char buf[1024];
  238.     int line = 0;
  239.     struct ServerEntry *entry;
  240.     LONG argarray[] = { NULL, NULL, NULL };
  241.     UBYTE *argstr = "HOST/A,LASTUSED/A/N,COMMENT/K";
  242.     struct RDArgs *rdargs;
  243.  
  244.     if (fh = Open("PROGDIR:Amster.servers", MODE_OLDFILE)) {
  245.         while (FGets(fh, buf, sizeof(buf))) {
  246.             line++;
  247.             if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  248.                 rdargs->RDA_Buffer = NULL;
  249.                 rdargs->RDA_Source.CS_Buffer = buf;
  250.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  251.                 argarray[2] = 0;
  252.                 if (ReadArgs(argstr, argarray, rdargs)) {
  253.                     if (entry = malloc(sizeof(struct ServerEntry))) {
  254.                         entry->Name = strdup((char *)argarray[0]);
  255.                         entry->LastOnline = *((long *)argarray[1]);
  256.                         if (argarray[2]) entry->Comment = strdup((char *)argarray[2]);
  257.                         else entry->Comment = strdup("");
  258.                         entry->Ping = -1;
  259.                         DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  260.                     }
  261.                 }
  262.                 else gui_debugf((char *)MSG_PARSE_ERROR, "PROGDIR:Amster.servers", line);
  263.                 FreeDosObject(DOS_RDARGS, rdargs);
  264.             }
  265.         }
  266.         Close(fh);
  267.         DoMethod(data->LV_Server, MUIM_NList_Sort);
  268.     }
  269. }
  270.  
  271.  
  272. void SaveServerList(struct NavigatorData *data)
  273. {
  274.     struct ServerEntry *entry;
  275.     BPTR fh;
  276.     char buf[1024], *tmp;
  277.     int i;
  278.  
  279.     fh = Open("PROGDIR:Amster.servers", MODE_NEWFILE);
  280.     if (!fh) return;
  281.  
  282.     for (i=0; ; i++) {
  283.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  284.         if (!entry) break;
  285.         if (entry->Comment) {
  286.             if (entry->Comment[0] != '\0') {
  287.                 tmp = strrep(entry->Comment, "\"", "*\"");
  288.                 sprintf(buf, "%s %ld COMMENT \"%s\"\n", entry->Name, entry->LastOnline, tmp);
  289.                 free(tmp);
  290.             }
  291.             else sprintf(buf, "%s %ld\n", entry->Name, entry->LastOnline);
  292.         }
  293.         else sprintf(buf, "%s %ld\n", entry->Name, entry->LastOnline);
  294.         Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
  295.     }
  296.  
  297.     Close(fh);
  298.     ServerListChanged = FALSE;
  299. }
  300.  
  301.  
  302. void MarkServerOnline(struct NavigatorData *data, char *server)
  303. {
  304.     struct ServerEntry *entry=0;
  305.     struct DateStamp *ds, *rds;
  306.     int i;
  307.     BOOL new = FALSE;
  308.  
  309.     for (i=0; ; i++) {
  310.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  311.         if (!entry) break;
  312.         if (strcmp(server, entry->Name) == 0) break;
  313.     }
  314.     if (!entry) {    /* Server not already on list */
  315.         if (prf->ServerList < 2) return;
  316.         if (entry = malloc(sizeof(struct ServerEntry))) {
  317.             entry->Name = strdup(server);
  318.             entry->LastOnline = 0;    /* In case we don't succeed later on... */
  319.             entry->Comment = strdup("");
  320.             entry->Ping = -1;
  321.             new = TRUE;
  322.         }
  323.     }
  324.  
  325.     if (ds = malloc(sizeof(struct DateStamp))) {
  326.         memset(ds, 0, sizeof(struct DateStamp));
  327.         if (rds = DateStamp(ds)) {
  328.             entry->LastOnline = rds->ds_Days*24*60*60 + rds->ds_Minute*60 + rds->ds_Tick/50;
  329.             if (new)
  330.                 DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  331.             else
  332.                 DoMethod(data->LV_Server, MUIM_NList_Redraw, i);
  333.             ServerListChanged = TRUE;
  334.         }
  335.         free(ds);
  336.     }
  337. }
  338.  
  339.  
  340. MUIF ServerListDisplay(REG(a2) char **array, REG(a1) struct ServerEntry *entry)
  341. {
  342.     struct DateTime dt;
  343.     static char buf[LEN_DATSTRING*2+6], buf2[20];
  344.     char datestring[LEN_DATSTRING], timestring[LEN_DATSTRING];
  345.  
  346.     if (entry) {
  347.         *array++ = entry->Name;
  348.         if (entry->LastOnline == 0) *array++ = "\33r-";
  349.         else {
  350.                 dt.dat_Stamp.ds_Days   = (entry->LastOnline)/(60*60*24);
  351.                 dt.dat_Stamp.ds_Minute = ((entry->LastOnline)%(60*60*24))/60;
  352.                 dt.dat_Stamp.ds_Tick   = ((entry->LastOnline)%60)*TICKS_PER_SECOND;
  353.                 dt.dat_Format = FORMAT_DOS;
  354.                 dt.dat_Flags = DTF_SUBST;
  355.                 dt.dat_StrDay = NULL;
  356.                 dt.dat_StrDate = datestring;
  357.                 dt.dat_StrTime = timestring;
  358.                 if (DateToStr(&dt)) {
  359.                     sprintf(buf, "\33r%s %s", datestring, timestring);
  360.                     *array++ = buf;
  361.                 }
  362.                 else *array++ = "\33r-";
  363.         }
  364.         *array++ = entry->Comment;
  365.  
  366.         if (entry->Ping >= 0) {
  367.             sprintf(buf2, "%ld", entry->Ping);
  368.             *array   = buf2;
  369.         }
  370.         else *array = "-";
  371.     }
  372.     else {
  373.         *array++ = (char *)MSG_NAVIGATOR_LIST_SERVER;
  374.         *array++ = (char *)MSG_NAVIGATOR_LIST_LASTONLINE;
  375.         *array++ = (char *)MSG_NAVIGATOR_LIST_COMMENT;
  376.         *array   = (char *)MSG_NAVIGATOR_LIST_PING;
  377.     }
  378.  
  379.     return 0;
  380. }
  381.  
  382.  
  383. MUIF ServerListCompare(REG(a0) struct Hook *hook, REG(a2) Object *obj, REG(a1) struct NList_CompareMessage *ncm)
  384. {
  385.     struct ServerEntry *entry1 = ncm->entry1;
  386.     struct ServerEntry *entry2 = ncm->entry2;
  387.     LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  388.     LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  389.     ULONG result = 0;
  390.  
  391.     if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
  392.  
  393.     if (col1 == 0) {
  394.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  395.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  396.         else
  397.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  398.     }
  399.     else if (col1 == 1) {
  400.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  401.             result = entry2->LastOnline - entry1->LastOnline;
  402.         else
  403.             result = entry1->LastOnline - entry2->LastOnline;
  404.     }
  405.     else if (col1 == 2) {
  406.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  407.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  408.         else
  409.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  410.     }
  411.     else if (col1 == 3) {
  412.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  413.             result = entry2->Ping - entry1->Ping;
  414.         else
  415.             result = entry1->Ping - entry2->Ping;
  416.     }
  417.  
  418.     if ((result != 0) || (col1 == col2)) return (result);
  419.  
  420.     if (col2 == 0) {
  421.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  422.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  423.         else
  424.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  425.     }
  426.     else if (col2 == 1) {
  427.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  428.             result = entry2->LastOnline - entry1->LastOnline;
  429.         else
  430.             result = entry1->LastOnline - entry2->LastOnline;
  431.     }
  432.     else if (col2 == 2) {
  433.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  434.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  435.         else
  436.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  437.     }
  438.     else if (col2 == 3) {
  439.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  440.             result = entry2->Ping - entry1->Ping;
  441.         else
  442.             result = entry1->Ping - entry2->Ping;
  443.     }
  444.  
  445.     return (result);
  446. }
  447.  
  448.  
  449. MUIF ServerListDestruct(REG(a2) APTR pool, REG(a1) struct ServerEntry *entry)
  450. {
  451.     free(entry);
  452.     return 0;
  453. }
  454.  
  455.  
  456. MUIF ServerString(REG(a0) struct Hook *hook, REG(a1) APTR *contents)
  457. {
  458.     DoMethod(gui->WI_Navigator, NAVI_REDRAWSERVER, contents);
  459.     return 0;
  460. }
  461.  
  462.